function oil = osl_run_oil(oil)

% oil = osl_run_ica(oil)
%
% Runs OSL's ICA pipeline using the settings contained in "oil", which 
% needs to be setup by calling oil=osl_setup_ica(S). All output results are
% saved to disk and stored in the "oil" structure.
%
% There are 6 stages which can be run:
%
% 1.) Source Reconstruction using the OSL beamformer
%     - oil.to_do(1) = 1.
%     - performed by osl_beamform.m
%     - beamformer parameter and output stored in "oil.source_recon"
% 2.) Estimation of down-sampled oscillatory envelope at each voxel
%     - oil.to_do(2) = 1.
%     - performed by osl_ica_preproc.m
%     - enveloping parameters and output stored in "oil.enveloping"
%     - beamformer result is converted to time domain, hilbert envelope
%       estimated and down-sampled. Envelopes are spatially smoothed and
%       resampled before being saved.
%       Analysis works for epoched data and continuous data.
% 3.) Concatentation and Normalisation
% 4.) ICA decomposition
% 5.) Subject Level Stats
% 6.) Group Level Stats
% 
% Henry Luckhoo (henry.luckhoo@trinity.ox.ac.uk)
% Version 1.1
% 010213

oil = osl_check_oil(oil);

% turns figure plotting on or off in SPM calls
spm_get_defaults('cmdline',~oil.do_plots);

%% Source Reconstruction

% make dir for the results:
if(isempty(findstr(oil.source_recon.dirname, '.oil')))
    oil.source_recon.dirname=[oil.source_recon.dirname, '.oil']; 
end;
if ~isdir(oil.source_recon.dirname); mkdir(oil.source_recon.dirname); end;

if(oil.to_do(1)),
  
    if(strcmp(oil.source_recon.method,'beamform')),
        oil.source_recon.results_fnames=osl_run_source_recon_beamform(oil);
    else
        error('recon_method is invalid');
    end;
    
    % save OIL to disk
    oil = osl_save_oil(oil);
 
end;
%% Conversion to Time Domain, Hilbert Enveloping, Down-sampling and Spatial
%% Smoothing
if(oil.to_do(2)),
    
    try
        tmp=oil.source_recon.results_fnames;
    catch
        error('Source recon stage has not been run. To load in a previous oil, try running "oil=osl_load_oil(oil.fname);" and then try this again.');
    end;
       
    S_in1=[];
    S_in1.window_length=oil.enveloping.window_length;                        % Hilbert envelope down-sampling window (s).
    S_in1.overlap=oil.enveloping.overlap;                                    % Window overlap (fraction e.g. 0.5)
    S_in1.timewindow=oil.enveloping.timewindow;                              % Time window of envelope to use in order to reduce Hilbert transform edge effects.
    S_in1.ds=oil.enveloping.gridstep;                                        % Spatial down-sampling resolution (mm).
    S_in1.ss=oil.enveloping.spatial_smoothing;                               % Spatial smoothing FWHM kernel (mm).
    %S_in1.do_weights_normalisation=oil.enveloping.do_weights_normalisation;  % Weights Normalisation Flag (sets weights = weights/(weights*weights');).
    S_in1.oil=oil;          
    if ~isdir([oil.source_recon.dirname '/' oil.enveloping.name]);mkdir([oil.source_recon.dirname '/' oil.enveloping.name]); end
    for sub=oil.source_recon.sessions_to_do
        [~, S_in1.source_recon_results_fname]=fileparts(oil.source_recon.results_fnames{sub});
        Sout = osl_ica_preproc(S_in1);
        oil.enveloping.results.source_space_envelopes_results_fnames{sub}=Sout.fils_nifti;
        oil.enveloping.results.source_space_envelopes_NoWeightsNorm_results_fnames{sub}=Sout.fils_nifti_nonorm;
    end
    
    % save OAT to disk
    oil = osl_save_oil(oil);
    
end;

%% Concatenation and Normalisation of Subjects
if(oil.to_do(3)), 
    
    % Check enveloping has been done
    try
        tmp = oil.enveloping.results.source_space_envelopes_results_fnames;
    catch
        error('Enveloping stage has has not been run. To load in a previous oil, try running "oil=osl_load_oil(oil.name);" and then try this again.');
    end;
    
    oil = osl_concat_subs(oil);

    % save OAT to disk
    oil = osl_save_oil(oil);
end;


%% ICA decomposition
if(oil.to_do(4)),

    if isfield(oil.concat_subs.results ,'concat_file')
        oil.ica.results.ica_concat_path{1}=[oil.source_recon.dirname '/' oil.enveloping.name '/' oil.concat_subs.name '/' oil.concat_subs.results.concat_file];
    end

    oil.ica.gridstep = oil.enveloping.gridstep;
    oil.ica.subj_ind = oil.concat_subs.results.subj_ind;
    oil.ica=osl_perform_ica(oil.ica);   
    oil.ica = rmfield(oil.ica, 'gridstep'); 
    oil.ica = rmfield(oil.ica, 'subj_ind'); 

    try
        switch lower(oil.ica.temp_or_spat)
            case {'spatial'};
                oil.ica.results.maps = osl_save_nii_ica_maps(oil,'spatial');
            case {'temporal'};
                oil.ica.results.maps = osl_save_nii_ica_maps(oil,'scaled_covariance');
        end
    catch
        warning('Unable to write ICA maps to nii file');
    end
    
    % save OAT to disk
    oil = osl_save_oil(oil);
end

%% First level stats
if(oil.to_do(5)), 
    try
        switch lower(oil.paradigm)
            case {'task'}
                tmp = oil.ica.results.mixing_matrix;
            case {'rest'}
                tmp = oil.enveloping.results.source_space_envelopes_NoWeightsNorm_results_fnames;
                tmp = oil.ica.results.mixing_matrix;
        end
    catch
        error('Enveloping or ICA stage has has not been run. To load in a previous oil, try running "oil=osl_load_oil(oil.name);" and then try this again.');
    end;
    
    switch lower(oil.paradigm)
        case {'task'}
            oil = osl_run_first_level_ica(oil);
        case {'rest'}
            oil = osl_single_subject_maps(oil);
        otherwise
            error('User must specify if data is "task" or "rest" in oil.paradigm')
    end
    
    % Save OAT to disk.
    oil = osl_save_oil(oil);
end

%% Group Level Stats
if(oil.to_do(6)), 
    try
        tmp = oil.ica_first_level.results;
    catch
        error('First level stats stage has has not been run. To load in a previous oil, try running "oil=osl_load_oil(oil.name);" and then try this again.');
    end;
    
    switch lower(oil.paradigm)
        case {'task'}
            oil = osl_run_group_level_ica(oil);
        case {'rest'}
            oil = osl_ica_maps_group_stats(oil);
        otherwise
            error('User must specify if data is "task" or "rest" in oil.paradigm')
    end
    
    % Save OAT to disk.
    oil = osl_save_oil(oil);
end
